package com.heo.server;

import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpHeaderNames.DATE;
import static io.netty.handler.codec.http.HttpHeaderNames.SERVER;
import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_0;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.sql.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.MethodNotSupportedException;
import org.apache.log4j.Logger;

import com.heo.pojo.DeviceInfoEntity;
import com.heo.pojo.DeviceModelEntity;
import com.heo.pub.ApplicationContextUtil;
import com.heo.pub.ServerConfig;
import com.heo.service.DeviceInfoService;
import com.heo.service.DeviceModelService;
import com.heo.util.GsonUtils;
import com.heo.util.Utils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
import io.netty.handler.codec.http.multipart.Attribute;

public class DeviceServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
	private static Logger log = Logger.getLogger(DeviceServerHandler.class);
	private static final AsciiString KEEP_ALIVE = new AsciiString("keep-alive");

	private String m = "";
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
	}

	@Override
	public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
		String remoteIpAddress = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
		try {
			if (HttpUtil.is100ContinueExpected(req)) {
				ctx.write(new DefaultFullHttpResponse(HTTP_1_0, CONTINUE));
			}
			String content = "";
			// 判断连接是否通过校验了
			if (req.uri().startsWith("/ewash/d/t")) {
				log.info("硬件设备ip[" + remoteIpAddress + "]");
				Map<String, String> parmMap = parseMap(req);
				String jsonString = parmMap.get("args");
				// 参数为空不返回
				if ("".equals(jsonString) || jsonString == null) {
					content = "args参数错误";
				}
				log.info("参数[" + jsonString + "]");
				Map<String, Object> reqJson = GsonUtils.jsonToMap(jsonString);
				m = Utils.getStr(reqJson.get("m"));
				if(Utils.checkNull(m)) {
					// 初始化设备，并入库
				    DeviceInfoService deviceInfoService = (DeviceInfoService) ApplicationContextUtil.getBeanById("deviceInfoService");
				    DeviceModelService deviceModelService = (DeviceModelService) ApplicationContextUtil.getBeanById("deviceModelService");
				    DeviceInfoEntity deviceInfo = deviceInfoService.getDeviceInfoMap(m);
				    if(deviceInfo == null) {
				    	throw new Exception(m + "设备不存在请联系管理员!!");
				    }
				    DeviceModelEntity deviceModel = deviceModelService.getDeviceModelMap(deviceInfo.getDeviceModelId());
				    String deviceServer = deviceModel.getDeviceServer();
				    String port = "" + ServerConfig.PORT;
				    String ip = ServerConfig.DEVICE_TCP_IP;
				    
				    if(Utils.checkNull(deviceServer)) {
				    	String[] ips = deviceServer.split(":");
				    	ip = ips[0];
				    	port = ips[1];
				    	if(!Utils.checkNull(port) || !Utils.checkNull(ip)) {
				    		port = "" + ServerConfig.PORT;
				    		ip = ServerConfig.DEVICE_TCP_IP;
				    	}
				    }
					Map<String, Object> rspJson = new HashMap<String, Object>();
					rspJson.put("l", 180);
					rspJson.put("p", port);
					rspJson.put("t", 10);
					if(deviceModel.getDeviceModelId() == 7) {
						rspJson.put("d", "00045100");
					}else if(deviceModel.getDeviceModelId() == 16) {
						rspJson.put("d", "00045101");
					}else {
						rspJson.put("d", "00045112");
					}
					rspJson.put("s", ip);
					content = GsonUtils.objectToJson(rspJson);
				}else {
					content = "m参数错误";
				}
			} else {
				content = "硬件设备ip[" + remoteIpAddress + "] 访问路径不正确";
			}
			log.info("返回：" + content);
//			boolean keepAlive = HttpUtil.isKeepAlive(req);
			// 向浏览器写入数据流
			FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer((content).getBytes("UTF-8")));
			response.headers().set(CONTENT_TYPE, "application/json;charset=UTF-8");
			response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
			response.headers().set(CONNECTION, HttpHeaderValues.CLOSE);
//			response.headers().set(CONTENT_TYPE, "text/html; charset=utf-8");
//			response.headers().set(DATE, "");
//			response.headers().set(SERVER, "");
//			ByteBuf buffer = Unpooled.copiedBuffer(content, CharsetUtil.UTF_8);
//			response.content().writeBytes(buffer);
//			buffer.release();
//			ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
//			if (!keepAlive) {
//				ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
//			} else {
//				ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
//			}
//			ctx.writeAndFlush(response);
			ctx.write(response);
	        ctx.flush();
//	        ChannelFuture future = ctx.channel().writeAndFlush(response);  
//	        future.channel().close();
//	        future.addListener(ChannelFutureListener.CLOSE);  
//			ctx.channel().writeAndFlush(response);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
//			throw e;
		} finally {
			ctx.channel().close();
			ctx.close();
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		log.error(cause.getMessage(), cause);
		ctx.close();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.info("[硬件设备][" + m + "]终端连接被断开。");
		ctx.close();
	}
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		super.channelReadComplete(ctx);
		// 刷新挂起的数据到远端
		ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
//		log.info("server channelReadComplete..");
//        ctx.flush();//刷新后才将数据发出到SocketChannel
	}

	/**
	 * 解析请求参数
	 * 
	 * @return 包含所有请求参数的键值对, 如果没有参数, 则返回空Map
	 *
	 * @throws BaseCheckedException
	 * @throws IOException
	 * @throws MethodNotSupportedException
	 */
	public Map<String, String> parseMap(FullHttpRequest fullReq) throws IOException, MethodNotSupportedException {
		HttpMethod method = fullReq.method();
		Map<String, String> parmMap = new HashMap<>();
		if (HttpMethod.GET == method) {
			// 是GET请求
			QueryStringDecoder decoder = new QueryStringDecoder(fullReq.uri());
			decoder.parameters().entrySet().forEach(entry -> {
				// entry.getValue()是一个List, 只取第一个元素
				parmMap.put(entry.getKey(), entry.getValue().get(0));
			});
		} else if (HttpMethod.POST == method) {
			// 是POST请求
			HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(fullReq);
			decoder.offer(fullReq);
			List<InterfaceHttpData> parmList = decoder.getBodyHttpDatas();
			for (InterfaceHttpData parm : parmList) {
				Attribute data = (Attribute) parm;
				parmMap.put(data.getName(), data.getValue());
			}
		} else {
			// 不支持其它方法
			throw new MethodNotSupportedException(""); // 这是个自定义的异常, 可删掉这一行
		}

		return parmMap;
	}
}
